﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using Newtonsoft.Json;

namespace Gmmy.Utility
{
    public static class EnumHelper
    {
        public static string getEnumName<T>(int i)
        {
            string[] names = Enum.GetNames(typeof(T));
            int[] values = (int[])Enum.GetValues(typeof(T));
            for (int j = 0; j < names.Length; j++)
            {
                if (values[j] == i) return names[j];
            }
            return "未知";
        }

        public static T Change2EnumType<T, K>(K n)
        {
            if (Enum.IsDefined(typeof(T), n))
            {
                T value = (T)Convert.ChangeType(n, Enum.GetUnderlyingType(typeof(T)));
                return value;
            }
            else
                throw new Exception(n + " is not defined");
        }

        public static bool CheckEnumValue<T, K>(K n)
        {
            if (Enum.IsDefined(typeof(T), n))
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 返回枚举中的对应的资源文件的值
        /// </summary>
        /// <param name="enum"></param>
        /// <returns></returns>
        public static string GetLocalizedDescription(this object @enum)
        {
            if (@enum == null)
                return null;

            string description = @enum.ToString();

            FieldInfo fieldInfo = @enum.GetType().GetField(description);
            DescriptionAttribute[] attributes =
                (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);

            if (attributes.Any())
                return attributes[0].Description;

            return description;
        }

        public static bool GetEnumShow(this object @enum)
        {
            if (@enum == null)
                return false;
            var attributes = @enum.GetType()
                .GetField(@enum.ToString())
                .GetCustomAttributes(typeof(ShowEnumAttribute), false);
            if (attributes.Any())
                return ((ShowEnumAttribute)attributes[0]).Show;
            return true;
        }

        /// <summary>
        /// 返回枚举的值
        /// </summary>
        /// <param name="enum"></param>
        /// <returns></returns>
        public static byte GetValue(this object @enum)
        {
            if (@enum == null)
                return 0;
            return (byte)@enum;
        }


        /// <summary>
        /// 返回枚举的值
        /// </summary>
        /// <param name="enum"></param>
        /// <returns></returns>
        public static int GetValueToInt(this object @enum)
        {
            if (@enum == null)
                return 0;
            return (int)@enum;
        }

        /// <summary>
        /// 返回枚举的值 格式化成字符串
        /// </summary>
        /// <param name="enum"></param>
        /// <returns></returns>
        public static string GetValueToString(this object @enum)
        {
            if (@enum == null)
                return "0";
            return ((byte)@enum).ToString();
        }

        /// <summary>
        /// 返回枚举的键名 格式化成字符串
        /// </summary>
        /// <param name="enum"></param>
        /// <returns></returns>
        public static string GetToString(this object @enum)
        {
            if (@enum == null)
                return "";
            return @enum.ToString();
        }

        /// <summary>
        /// 返回是否
        /// </summary>
        /// <param name="bl"></param>
        /// <returns></returns>
        public static string GetBoolenDescription(this bool @bl)
        {
            if (@bl)
                return "是";
            else
                return "否";
        }

        /// <summary>
        /// 返回性别
        /// </summary>
        /// <param name="bl"></param>
        /// <returns></returns>
        public static string GetSexDescription(this bool @bl)
        {
            if (@bl)
                return "男";
            else
                return "女";
        }

        public static string EnumTypeToJson<T>() where T : new()
        {
            T mt = new T();
            var t = mt.GetType();
            var list = (from int i in Enum.GetValues(t)
                select
                new
                {
                    Text = EnumHelper.GetLocalizedDescription(Enum.ToObject(t, i)),
                    Value = i.ToString(),
                }).ToList();
            return JsonConvert.SerializeObject(list);
        }

    }

    public class LocalizedEnumAttribute : DescriptionAttribute
    {
        private PropertyInfo _nameProperty;
        private Type _resourceType;

        public LocalizedEnumAttribute(string displayNameKey)
            : base(displayNameKey)
        {

        }

        public Type NameResourceType
        {
            get
            {
                return _resourceType;
            }
            set
            {
                _resourceType = value;

                _nameProperty = _resourceType.GetProperty(this.Description, BindingFlags.Static | BindingFlags.Public);
            }
        }

        public override string Description
        {
            get
            {
                //check if nameProperty is null and return original display name value 
                if (_nameProperty == null)
                {
                    return base.Description;
                }

                return (string)_nameProperty.GetValue(_nameProperty.DeclaringType, null);
            }
        }
    }
    [AttributeUsage(AttributeTargets.Field)]
    public class ShowEnumAttribute : Attribute
    {
        /// <summary>
        /// 指定此特性绑定到的属性为只读，并且不能在服务器资源管理器中修改。此 static 字段是只读的。
        /// </summary>
        public static readonly ShowEnumAttribute Yes = new ShowEnumAttribute(true);
        /// <summary>
        /// 指定该特性绑定到的属性为读/写属性，可以修改。此 static 字段是只读的。
        /// </summary>
        public static readonly ShowEnumAttribute No = new ShowEnumAttribute(false);
        /// <summary>
        /// 指定 <see cref="T:System.ComponentModel.ReadOnlyAttribute"/> 的默认值，为 <see cref="F:System.ComponentModel.ReadOnlyAttribute.No"/>（即此特性绑定到的属性是可读/写的）。此 static 字段是只读的。
        /// </summary>
        public static readonly ShowEnumAttribute Default = ShowEnumAttribute.No;
        private bool show;

        /// <summary>
        /// 获取一个值，该值指示该特性绑定到的属性是否为只读属性。
        /// </summary>
        /// 
        /// <returns>
        /// 如果该特性所绑定到的属性为可显示属性，则为 true；如果该属性为不显示属性，则为 false。
        /// </returns>
        public bool Show
        {
            get
            {
                return this.show;
            }
        }

        /// <summary>
        /// 初始化 <see cref="T:ShowEnumAttribute"/> 类的新实例。
        /// </summary>
        /// <param name="show">如果该特性所绑定到的属性为可显示属性，则为 true；如果该属性为不显示属性，则为 false。</param>
        public ShowEnumAttribute(bool show)
        {
            this.show = show;
        }

        /// <summary>
        /// 指示此实例与指定对象是否相等。
        /// </summary>
        /// 
        /// <returns>
        /// 如果 <paramref name="value"/> 等于此实例，则为 true；否则为 false。
        /// </returns>
        /// <param name="value">要比较的另一个对象。</param>
        public override bool Equals(object value)
        {
            if (this == value)
                return true;
            ShowEnumAttribute readOnlyAttribute = value as ShowEnumAttribute;
            if (readOnlyAttribute != null)
                return readOnlyAttribute.Show == this.Show;
            return false;
        }

        /// <summary>
        /// 返回此实例的哈希代码。
        /// </summary>
        /// 
        /// <returns>
        /// 当前 <see cref="T:System.ComponentModel.ReadOnlyAttribute"/> 的哈希代码。
        /// </returns>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        /// <summary>
        /// 确定此特性是否为默认特性。
        /// </summary>
        /// 
        /// <returns>
        /// 如果此特性是此特性类的默认值，则为 true；否则为 false。
        /// </returns>
        public override bool IsDefaultAttribute()
        {
            return this.Show == ShowEnumAttribute.Default.Show;
        }
    }
}
